﻿using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Controls;
using Castle.Windsor;
using SuppKids.Core.Domain;
using SuppKids.Core.Extensions;
using SuppKids.Core.Services;
using SuppKids.Core.Stuff;
using SuppKids.Resources;
using SuppKids.ViewModels;
using System.Dynamic;

using System.Data.Entity.Validation;

namespace SuppKids
{
    /*
    public class DynamicObj : DynamicObject, IDictionary<string, object>
    {
        // Wrap an internal dictionary
        // Override DynamicObject's TryGetProperty(), TrySetProperty()          Methods.    
    }
    */
	public partial class DatabaseEditor : BaseWindow
	{
		private readonly DishService dishService;
		private readonly ProductService productService;
        private readonly NormService normService;
		private readonly GroupService groupService;
		private readonly StuffInfoStorage stuffInfoStorage;
        //private IDictionary<string, object>[] gridObject;
        private bool showGroupsInTable;
        private int currPage;
        private int totalPages;
        private int onPage;
        private bool newProduct;
        private int totalProd;
		public DatabaseEditor(IWindsorContainer container, LicenseService licenseService, DishService dishService,
            ProductService productService, GroupService groupService, StuffInfoStorage stuffInfoStorage, NormService normService)
			: base(container, licenseService)
		{
			this.dishService = dishService;
			this.productService = productService;
            this.normService = normService;
			this.groupService = groupService;
			this.stuffInfoStorage = stuffInfoStorage;
			InitializeComponent();
			this.SetDishEditorDataContext();
			this.SetProductEditorDataContext();
			this.SetGroupEditorDataContext();
			this.StuffInfoTab.DataContext = stuffInfoStorage.Get();
            this.newProduct = true;
            this.PagePrev.IsEnabled = false;
            this.PageNext.IsEnabled = false;
            this.showGroupsInTable = false;
            this.CurrPageTextBox.IsEnabled = false;
            this.currPage = 1;
            this.onPage = 19;
            this.totalPages = 0;

            int row = 0;
            foreach( Group group in AllGroups) {
                TextBox txt = new TextBox();
                txt.Name = "group_" + group.Id;    
                Label lbl = new Label();
                lbl.Content = group.Name;
                RowDefinition rowDef = new RowDefinition();
                rowDef.Height = new GridLength(30);
                this.CurrGroupsGrid.RowDefinitions.Add(rowDef);
                this.CurrGroupsGrid.Children.Add(lbl);
                Grid.SetColumn(lbl, 0);
                Grid.SetRow(lbl, row);
                this.CurrGroupsGrid.Children.Add(txt);
                Grid.SetColumn(txt, 1);
                Grid.SetRow(txt, row);

                if (this.showGroupsInTable)
                {
                    DataGridTextColumn col = new DataGridTextColumn();
                    col.Header = group.Name;
                    col.Binding = new Binding("group_" + group.Id);
                    this.AllProductsGrid.Columns.Add(col);
                }
                row++;
            }

            //this.totalProd = this.productService.GetAll().Count();
		}

        class ItemsGrid : Product { 
        
        }
		public IEnumerable<Dish> AllDishes
		{
			get
			{
				var filterText = this.DishFilter.Text.With(a => a.ToLowerInvariant());
				var items = this.dishService.GetAll();
				if (string.IsNullOrWhiteSpace(filterText))
				{
					return items;
				}

				return items.Where(a => a.Name.ToLowerInvariant().StartsWith(filterText));
			}
		}

        public IEnumerable<Product> AllProducts 
		{
			get
			{
				var filterText = this.ProductFilter.Text.With(a => a.ToLowerInvariant());
                var items = this.productService.GetAll();

				if (string.IsNullOrWhiteSpace(filterText))
				{
					return items;
				}
				return items.Where(a => a.Name.ToLowerInvariant().StartsWith(filterText));
			}
		}
        public IEnumerable<IDictionary<string, object>> AllProductsWithGroups
        {
            get
            {             
                var filterText = this.ProductFilter.Text.With(a => a.ToLowerInvariant());
				// !!! исправить бля
                var items = this.productService.GetAll();
                this.totalProd = items.Count();

                if (this.showGroupsInTable)
                {
                    //int totalProd = items.Count();
                    this.totalPages = (this.totalProd - 1 ) / this.onPage + 1;
                    items = this.productService.GetPageOrderedById(this.currPage, this.onPage, out this.totalProd);
                    this.totalProd = items.Count();
                    reloadPagePanelObjects();
                }
                
                if (!string.IsNullOrWhiteSpace(filterText))
                    //items.Where(a => a.Name.ToLowerInvariant().StartsWith(filterText)); 
                    items = this.productService.GetAll().Where(a => a.Name.ToLowerInvariant().StartsWith(filterText));

                List<IDictionary<string, object>> fullItems = new List<IDictionary<string, object>>();//= new ExpandoObject() as IDictionary<string, object>;
                /*
                var row = new ExpandoObject() as IDictionary<string, object>;
                row.Add("Name", "");
                row.Add("Cipher", "");
                row.Add("Price", "");
                foreach (var item in items){
                    foreach (var norm in item.Norms)
                        row.Add("group_" + norm.Group.Id, "");
                    break;
                }
                */
                int counter = 1;
                foreach (var item in items)
                {
                    
                    var row = new ExpandoObject() as IDictionary<string, object>;
                    row.Add("Id", item.Id);
                    row.Add("Name", item.Name);
                    row.Add("Cipher", item.Cipher);
                    row.Add("Price", item.Price);
                    if (this.showGroupsInTable) { 
                        try
                        {
                            foreach (var norm in item.Norms)
                                row.Add("group_" + norm.Group.Id, norm.Value);  
                        }
                        catch { }
                    }
                    /*
                    row["Name"] = item.Name;
                    row["Cipher"] = item.Cipher;
                    row["Price"] = item.Price;
                    foreach (var norm in item.Norms)
                        row["group_" + norm.Group.Id] = norm.Value;
                    */
                    fullItems.Add(row);

                    counter++;
                    if (counter > this.onPage && this.showGroupsInTable )
                        break;
                }
                return fullItems;
            }
        }
		public IEnumerable<Group> AllGroups
		{
			get
			{
				var filterText = this.GroupFilter.Text.With(a => a.ToLowerInvariant());
				var items = this.groupService.GetAll();
				if (string.IsNullOrWhiteSpace(filterText))
				{
					return items;
				}

				return items.Where(a => a.Name.ToLowerInvariant().StartsWith(filterText));
			}
		}

        private void UpdateAllProductsGrid(bool reload = false)
        {
            if (reload)
            {
                //this.AllProductsGrid.ClearValue(DataGrid.ItemsSourceProperty);
                if (this.showGroupsInTable)
                {
                    foreach (Group group in AllGroups)
                    {
                        DataGridTextColumn col = new DataGridTextColumn();
                        col.Header = group.Name;
                        col.Binding = new Binding("group_" + group.Id);
                        this.AllProductsGrid.Columns.Add(col);
                    }
                }
                else
                {
                    this.AllProductsGrid.Columns.Clear();
                    DataGridTextColumn col = new DataGridTextColumn();
                    col.Header = "Название";
                    col.Binding = new Binding("Name");
                    this.AllProductsGrid.Columns.Add(col);
                    DataGridTextColumn col2 = new DataGridTextColumn();
                    col2.Header = "Шифр";
                    col2.Binding = new Binding("Cipher");
                    this.AllProductsGrid.Columns.Add(col2);
                    DataGridTextColumn col3 = new DataGridTextColumn();
                    col3.Header = "Цена";
                    col3.Binding = new Binding("Price");
                    this.AllProductsGrid.Columns.Add(col3);
                }
            }
            
            this.AllProductsGrid.GetBindingExpression(DataGrid.ItemsSourceProperty).UpdateTarget();
        }

		private void NewDishButtonClick(object sender, RoutedEventArgs e)
		{
			this.SetDishEditorDataContext();
		}

		private void SaveDishButtonClick(object sender, RoutedEventArgs e)
		{
			var viewModel = (Dish)this.DishEditorBox.DataContext;
			if (!string.IsNullOrWhiteSpace(viewModel.Name))
			{
				var isTransient = viewModel.IsTransient;
				this.dishService.RegisterSave(viewModel, true);

				if (isTransient)
				{
					this.AllDishesGrid.GetBindingExpression(DataGrid.ItemsSourceProperty).UpdateTarget();
				}

				MessageBox.Show(Messages.DishSaved);
			}
		}
        private void RemoveDishButtonClick(object sender, RoutedEventArgs e)
        {
            var dishToRemove = (Dish)this.DishEditorBox.DataContext;

            if (!dishToRemove.IsTransient && MessageBox.Show(Messages.DeleteDishConfirmation, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                
                try
                {
                    if (dishToRemove.DailyMenus.Count() == 0 && dishToRemove.DishAmounts.Count() == 0 && dishToRemove.Ingredients.Count() == 0 )
                        this.dishService.RegisterDelete(dishToRemove, true);
                    else
                        MessageBox.Show(Messages.CanNotRemoveDish);
                }
                catch
                {                 
                    MessageBox.Show(Messages.CanNotRemoveDish);
                }
                this.AllDishesGrid.GetBindingExpression(DataGrid.ItemsSourceProperty).UpdateTarget();
            }

        }
		private void SetDishEditorDataContext()
		{
			this.DishEditorBox.DataContext = new Dish();
		}

		private void AllDishesGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			var dish = this.AllDishesGrid.SelectedItem as Dish ?? new Dish();
			this.DishEditorBox.DataContext = dish;
		}

		private void NewProductButtonClick(object sender, RoutedEventArgs e)
		{
			this.SetProductEditorDataContext();
		}

		private void SaveProductButtonClick(object sender, RoutedEventArgs e)
		{
            try{
                Product viewModel;
                if (!this.newProduct || this.AllProductsGrid.SelectedItem != null)
                {
                    var row = (IDictionary<string, object>)this.ProductEditorBox.DataContext;
                    int id = int.Parse(row.Values.First().ToString());
                    viewModel = this.productService.GetOneById(id);
                    int field = 0;
                    foreach( var value in row.Values) {

                        if (value == null)
                        {
                            field++;
                            continue;
                        }
                        switch (field)
                        {
                            case 1:
                                viewModel.Name = value.ToString();
                                break;
                            case 2:
                                viewModel.Cipher = value.ToString();
                                break;
                            case 3:
                                viewModel.Price = int.Parse(value.ToString());
                                break;
                        }
                        if (field >= 3)
                            break;
                        field++;
                    }
                    var norms = this.normService.GetQuery().Where(a => a.Product.Id == id);
                    foreach (var norm in norms)
                        this.normService.RegisterDelete(norm, true);

                }else
                    viewModel = (Product)this.ProductEditorBox.DataContext;
            
			    //var viewModel = (Product)this.ProductEditorBox.DataContext;

                //List<Norm> norms = new List<Norm>();

                // херово, но работает.
                /*
                
                for (int n = 0; n < viewModel.Norms.Count(); n++) { 
                    ICollection<Norm> currNorms = viewModel.Norms;
                    foreach (var norm in currNorms) { 
                        this.normService.RegisterDelete(norm, true);
                        break;
                    }
                }
                */
                //try
                //{    
                int index = 1;
                foreach (Group group in AllGroups)
                {
                    TextBox txt = (TextBox)this.CurrGroupsGrid.Children[index];
                    double normValue = 0;
                    if (txt.Text != "")
                        normValue = double.Parse(txt.Text);
                    Norm norm = new Norm(viewModel, group, normValue);
                    viewModel.Norms.Add(norm);
                    index += 2;
                }


			    if (!string.IsNullOrWhiteSpace(viewModel.Name))
			    {
				    var isTransient = viewModel.IsTransient;

				    this.productService.RegisterSave(viewModel, true);
                    
                    //if (this.showGroupsInTable)
                        //this.UpdateAllProductsGrid();
				    if (isTransient)
				    {
					    //this.AllProductsGrid.GetBindingExpression(DataGrid.ItemsSourceProperty).UpdateTarget();
                        this.UpdateAllProductsGrid();
				    }
                
				    MessageBox.Show(Messages.ProductSaved);
			    }
            }
            catch { }
		}
        private void RemoveProductButtonClick(object sender, RoutedEventArgs e)
        {
            var row = (IDictionary<string, object>)this.ProductEditorBox.DataContext;
            int id = int.Parse(row.Values.First().ToString());
            Product productToRemove = this.productService.GetOneById(id);
            //var productToRemove = (Product)this.ProductEditorBox.DataContext;

            if (!productToRemove.IsTransient && MessageBox.Show(Messages.DeleteProductConfirmation, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                try
                {
                    if (productToRemove.Ingredients.Count() == 0 )
                        this.productService.RegisterDelete(productToRemove, true);
                    else
                        MessageBox.Show(Messages.CanNotRemoveProduct);
                }
                catch
                {
                    MessageBox.Show(Messages.CanNotRemoveProduct);
                }
                //this.AllProductsGrid.GetBindingExpression(DataGrid.ItemsSourceProperty).UpdateTarget();
                this.UpdateAllProductsGrid();
            }

        }
		private void SetProductEditorDataContext()
		{
            this.newProduct = true;
            this.ProductEditorBox.DataContext = new Product();
            /*
            int index = 1;
            foreach (Group group in AllGroups)
            {
                TextBox txt = (TextBox)this.CurrGroupsGrid.Children[index];
                txt.Text = "0";
                index += 2;
            }
            */
		}

		private void AllProductsGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			this.ProductEditorBox.DataContext = this.AllProductsGrid.SelectedItem ?? new Product();
            //this.CurrGroupsGrid.DataContext = this.AllProductsGrid.SelectedItem;
            this.newProduct = false;
            if (this.AllProductsGrid.SelectedItem != null && this.showGroupsInTable && false) //!!!
            {
                var item = (IDictionary<string, object>)this.AllProductsGrid.SelectedItem;
                int index = 1, col = 4;
                foreach( Group group in AllGroups) 
                {
                    TextBox txt = (TextBox)this.CurrGroupsGrid.Children[index];
                    txt.Text = "0";
                    int colValue = 0;
                    foreach (var value in item.Values)
                    {
                        if (col == colValue)
                        {
                            txt.Text = value.ToString();
                            break;
                        }
                        colValue++;
                    }
                    col++;
                    index += 2;
                }
            }
            else if (this.AllProductsGrid.SelectedItem != null ) {
                var item = (IDictionary<string, object>)this.ProductEditorBox.DataContext;

                var id = int.Parse(item.Values.First().ToString());
                var norms = this.normService.GetQuery().Where(a => a.Product.Id == id ); 
                int index = 1;
                foreach (Group group in AllGroups)
                {
                    TextBox txt = (TextBox)this.CurrGroupsGrid.Children[index];
                    txt.Text = "0";
  
                    foreach (var norm in norms)
                        if (txt.Name == "group_" + norm.Group.Id.ToString() && id == norm.Product.Id) 
                        {
                            txt.Text = norm.Value.ToString();
                            break;
                        }
                    
                    index += 2;
                }           
            }
		}

		private void NewGroupButtonClick(object sender, RoutedEventArgs e)
		{
			this.SetGroupEditorDataContext();
		}

		private void SaveGroupButtonClick(object sender, RoutedEventArgs e)
		{
			var viewModel = (Group)this.GroupEditorBox.DataContext;
			if (!string.IsNullOrWhiteSpace(viewModel.Name))
			{
				var isTransient = viewModel.IsTransient;
				this.groupService.RegisterSave(viewModel, true);

				if (isTransient)
				{
					this.AllGroupsGrid.GetBindingExpression(DataGrid.ItemsSourceProperty).UpdateTarget();
				}

				MessageBox.Show(Messages.GroupSaved);
			}
		}

		private void SetGroupEditorDataContext()
		{
			this.GroupEditorBox.DataContext = new Group();
		}

		private void AllGroupsGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			this.GroupEditorBox.DataContext = this.AllGroupsGrid.SelectedItem ?? new Group();
		}

		private void DishFilter_OnTextChanged(object sender, TextChangedEventArgs e)
		{
			this.AllDishesGrid.GetBindingExpression(DataGrid.ItemsSourceProperty).UpdateTarget();
		}

		private void ProductFilter_OnTextChanged(object sender, TextChangedEventArgs e)
		{
			//this.AllProductsGrid.GetBindingExpression(DataGrid.ItemsSourceProperty).UpdateTarget();
            this.UpdateAllProductsGrid();
		}

		private void GroupFilter_OnTextChanged(object sender, TextChangedEventArgs e)
		{
			this.AllGroupsGrid.GetBindingExpression(DataGrid.ItemsSourceProperty).UpdateTarget();
		}

		private void RemoveGroupButtonClick(object sender, RoutedEventArgs e)
		{
			var groupToRemove = (Group)this.GroupEditorBox.DataContext;

			if (!groupToRemove.IsTransient && MessageBox.Show(Messages.DeleteGroupConfirmation, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
			{
				this.groupService.RegisterDelete(groupToRemove, true);
				this.AllGroupsGrid.GetBindingExpression(DataGrid.ItemsSourceProperty).UpdateTarget();
			}

		}

		private void SaveStuffButtonClick(object sender, RoutedEventArgs e)
		{
			this.stuffInfoStorage.Set((StuffInfo) this.StuffInfoTab.DataContext);
			MessageBox.Show(Messages.StuffInfoSuccessfullySaved);
		}

        private void showGroupsInTableClick(object sender, RoutedEventArgs e)
        {
            bool? show = this.showGroupsInTableCheckBox.IsChecked;
            this.showGroupsInTable = (bool)show;

            this.currPage = 1;
            this.UpdateAllProductsGrid(true);
            this.reloadPagePanelObjects();
        }

        private void NextPageClick(object sender, RoutedEventArgs e)
        {
            if (goToPage())
                this.currPage++;
            this.UpdateAllProductsGrid();
            this.reloadPagePanelObjects();
        }

        private void PrevPageClick(object sender, RoutedEventArgs e)
        {
            if (goToPage())
                this.currPage--;
            this.UpdateAllProductsGrid();
            this.reloadPagePanelObjects();
        }

        private bool goToPage()
        {
            int CurrPageTextBoxValue = int.Parse(this.CurrPageTextBox.Text);
            if (this.currPage != CurrPageTextBoxValue && CurrPageTextBoxValue >= 1 && CurrPageTextBoxValue <= this.totalPages)
            {
                this.currPage = CurrPageTextBoxValue;
                return false;
            }
            return true;
        }

        private void reloadPagePanelObjects()
        {
            if (this.showGroupsInTable)
            {
                this.CurrPageTextBox.Text = this.currPage.ToString();
                this.TotalPagesText.Text = "/ "+ this.totalPages.ToString();
                this.CurrPageTextBox.IsEnabled = true;
                if (this.currPage == 1)
                    this.PagePrev.IsEnabled = false;
                else
                    this.PagePrev.IsEnabled = true;

                if (this.currPage >= this.totalPages)
                    this.PageNext.IsEnabled = false;
                else
                    this.PageNext.IsEnabled = true;
            }
            else
            {
                this.PagePrev.IsEnabled = false;
                this.PageNext.IsEnabled = false;
                this.CurrPageTextBox.IsEnabled = false;
                this.CurrPageTextBox.Text = "1";
                this.TotalPagesText.Text = "/ 1";
            }
        }
	}
}